# AtomBot Lua2TNS v0.1 - a little IRC bot that assembles little things! :)
# (C) Copyright 2011 Albert H. (alberthro)
# 
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
# 
# Thanks to everybody at #cemetech and #omnimaga who helped me develop 
# and test this! :D
# 
# Patches are always welcome for new features! ;)
# Project website: http://code.google.com/p/atombot/
# ============================================================================
# To use this bot, you need Python. Install it from http://www.python.org/.
# You may or may not need more modules in order to run this bot.
# 
# Have fun with the bot! :D It's recommended that you change the settings
# below, since they are already in use by another person. (Hint: Me! ;) )
# 
# Changelog:
# v1.0
#   - Initial release.
# 

import sys 
import socket 
import string 
import os 
import traceback
import xml.dom.minidom as minidom
import threading
import urllib, urllib2
import time
import re, htmlentitydefs
import subprocess
import datetime

#import os
#import urllib2
import tempfile
#import subprocess
import shutil, glob

import lua2tnscore

import random

# Below are variables that you can alter.

###################################
# Server connection information
###################################

# Server host
HOST = 'irc.mzima.net'
# Server port
PORT = 6667
# IRC nick
NICK = 'Lua2TNS'
# IRC password, if needed
PASS = ''
# IRC ident
IDENT = 'AtomBotLua' 
# IRC real name field
REALNAME = 'AtomBot Lua2TNS' 

###################################
# Bot settings
###################################
# Bot owner
OWNER='alberthro' 
# Channel autoconnect list
CHANNELINIT = [ '#thebot', '#nspire-lua' ]#, '#cemetech', '#choose-game' ]
# Channels with colorful output
COLORFULCHANS = [ '#omnimaga', '#thebot', '#choose-game' ]
# Channels that can have annoucements when the bot arrives
ANNOUNCECHANS = [ '#thebot', '#choose-game' ]
# The announce message when the bot joins
ANNOUNCEMSG = "Hi everyone! You guys are awesome! :)"
# No death message channels
NODIECHANS = [ '#omnimaga', '#cemetech' ]
# Auto rejoin chans
AUTOREJOIN_CHANS = [ '#thebot' ]
# Bad words list
BADWORDS=[ "boobies", "boobs", "fuck", "shit", "cunt", "dick", "Casio", "titties", "dick",
"tits", "cock", "badwordtest", "fap", "bewb" ]
# Channels that require censoring of explicit words
CLEANCHANS = [ '#cemetech' ]
# Channels that require absolute silence, temporaily or not
SILENTCHANS = [ '#omnimaga' ]
# Bot call character
CALLCHAR = "$"
# Auto ops people list
OPS=[ 'alberthro', 'qazz42', 'alberth', 'qazzbot', 'DThought', 'AaronBot',
'ArthurH', 'HelloBot', 'MouseBot', 'StickyBot', 'epicfail', 'tanner', 'grphmstur',
'Buckeye', 'MrAtom', 'MrAtom2', 'AtomASM', 'alb|vps',
'geekbozu', 'alb|57o9', 'Runer112', 'Eeems_', 'Eeems', 'apcalc', 'Zeda', 'Zeda_', 'Deep_Blue', 'MrAtom', 'alb|hw', 'alb|away',
'alb|ZNC', 'jimbauwen', 'david', 'david__', 'Scout' ]
# Can the people in the OPS list control the bot too? (Like an owner)
# 1 for yes, 0 for no
OPS_CAN_CONTROL_BOT = 1
# Is logging enabled for the bot?
# 1 for yes, 0 for no
LOG_TO_FILE = 1
# Log file name
LOGFILE = "AtomBot.log"
# Send any errors to the owner?
# 1 for yes, 0 for no
SEND_ERROR_TO_OWNER = 1
# Disable the raw command?
# 1 to disable, 0 for enable
DISABLE_RAW_COMMAND = 0

###################################
# Bot output/debugging settings
###################################
# Enable debug output?
# 1 for yes, 0 for no. Use 0 unless you are
# trying to debug the bot.
ENABLE_DEBUG = 0
# Enable IRC printing of regular output? 
# 1 for yes, 0 for no. STRONGLY SUGGEST 0!
ENABLE_IRC_PRINT = 0
# Enable IRC printing of debug output?
# 1 for yes, 0 for no. STRONGLY SUGGEST 0!
ENABLE_IRC_PRINT_DEBUG = 0
# Make the bot super silent?
# 1 for yes, 0 for no. This will only print the
# author, and other parts. Nothing else will be 
# printed. Recommended 0 ONLY if you're not debugging,
# nor are interested in who's controlling it.
# Note that this setting OVERRIDES all the other settings!
ENABLE_SUPER_SILENT = 0
###################################
# System settings
###################################
# Allow people to run system commands from IRC?
# 1 for yes, 0 for no.
RUN_SYS_COMMANDS=0

#OPS=[ 'alberthro', 'qazz42', 'alberth', 'dTal', 'qazzbot', 'DThought', 'AaronBot', 'ArthurH', 'HelloBot', 'MouseBot', 'StickyBot'	 ]

####################################################
# That's all! DO NOT CHANGE ANY VARIABLES BELOW!
####################################################

# Messages from server are stored here - including chat, etc.
readbuffer=''

# Program version
VERSION="0.1"

# Global defines for socket, channel list, IRC connection, 
# thread handle, title and link vars
global s, IRC_CONNECTED
global IN_CHANS
global DISABLE_RAW_COMMAND

# Internal channel list, blank on start
IN_CHANS = []

# Set the IRC_CONNECTED (IRC connection) variable to 0, since we haven't
# connected yet!
IRC_CONNECTED=0

# Set LOG_FAILED to 0, since nothing has failed yet!
LOG_FAILED = 0

# The assembling thread class.
class ConvertIt (threading.Thread):
	def __init__ ( self, sock, channel, user, src, target ):
		self.sock = sock
		self.channel = channel
		self.user = user
		self.src = src
		self.target = target
		self.stopnow = 0
		self.jobid = random.randrange(10000,99999)
		self.finalurl = "http://withg.us.to/lua2tns/"
		threading.Thread.__init__(self)
	def stopThread(self):
		print_r("[ForumXMLParse] Got signal to exit.")
		self.stopnow = 1
	def checkExit(self):
		if self.stopnow == 1:
			print_r("Au revoir from ConvertIt thread!")
			exit()
	def moveFiles(self,tmpdir, target):
		shutil.move(tmpdir, target)
	def chownRecursive(self, dirname, perm):
		print "[ConvertIt] Changing permissions of "+dirname+" to "+str(perm)+"..."
		os.chmod(dirname, perm)
		for file in os.listdir(dirname):
			print "[ConvertIt] Changing permissions of "+os.path.join(dirname, file)+" to "+str(perm)+"..."
			os.chmod(os.path.join(dirname, file), perm)
	def run(self):
		print "[ConvertIt] Starting assembling for job "+str(self.jobid)+"..."
		try: 
			while self.stopnow != 1:
				global s
				print_d("[ConvertIt] Launching assembler for job "+str(self.jobid)+"...")
				res = lua2tnscore.compile_file(self.jobid, self.src, self.target)
				self.moveFiles(res[1], "/var/www/lua2tns/"+str(self.jobid))
				# Note to self: python LOVES octal numbers, hence 0777 instead of 777. :P
				self.chownRecursive("/var/www/lua2tns/"+str(self.jobid), 0777)
				if res[0] != 0:
					# It failed! But... let's double check the result.
					if len(res) != 2 and file_exists(os.path.join(res[1], target)):
						# That's strange...
						self.sock.sendall('PRIVMSG '+self.channel+" :"+self.user+": Lua2TNS | It seems to have built, but the builder says otherwise. Check the logs carefully for any errors. The files are here: "+self.finalurl+str(self.jobid)+"/"+"\r\n")
					else:
						# Yup, it failed. Notify the user.
						self.sock.sendall('PRIVMSG '+self.channel+" :"+self.user+": Lua2TNS | It failed terribly! :( Logs and more here: "+self.finalurl+str(self.jobid)+"/lua2tnslog.txt"+"\r\n")
				elif res[0] == 0:
					# Success! Report the built file... but check for the length first.
					if len(res) > 2:
						self.sock.sendall('PRIVMSG '+self.channel+" :"+self.user+": Lua2TNS | Success! :D "+self.finalurl+str(self.jobid)+"/"+self.target+" | All files, including logs @ "+self.finalurl+str(self.jobid)+"/lua2tnslog.txt"+"\r\n")
					else:
						self.sock.sendall('PRIVMSG '+self.channel+" :"+self.user+": Lua2TNS | It seems to have built, but the output messed up. This could (potentially) be bad. Report this immediately. Anyway, the files are here: "+self.finalurl+str(self.jobid)+"/lua2tnslog.txt"+"\r\n")
				self.stopnow = 1
				
			print_d("[ConvertIt] Job "+str(self.jobid)+" complete.")
		except Exception, err:
			minorCrashFail(err)
			self.sock.sendall('PRIVMSG '+self.channel+" :"+self.user+": YIKES! Lua2TNS crashed! Please report this bug immediately! O_O"+"\n")


# AssembleItHandler = AssembleIt(s, currchan, user, prgm, src, target)
# AssembleItHandler.start()

# Printing functions

# Debug printing
def print_d(string):
	global IRC_CONNECTED
	if ENABLE_DEBUG == 1 and ENABLE_SUPER_SILENT != 1:
		print string
	if (ENABLE_IRC_PRINT_DEBUG == 1 and IRC_CONNECTED == 1):
		s.sendall("PRIVMSG "+CHANNELINIT+" :[AtomBot] "+string+"\r\n")

# Print to both term and IRC, silencable printing
def print_r(string):
	global IRC_CONNECTED
	if (ENABLE_IRC_PRINT == 1 and IRC_CONNECTED == 1):
		s.sendall("PRIVMSG "+CHANNELINIT+" :[AtomBot] "+string+"\r\n")
	if ENABLE_SUPER_SILENT != 1:
		print string

# Local print function, no silencing
def print_i(string):
	print string

# Error printing
def print_e(string):
	print string

def findelement(string, thelist):
	"""Return first item in sequence where f(item) == True."""
	print_d("[DEBUG] [FindElement] Search item is "+string)
	print_d("[DEBUG] [FindElement] List to look inside of is "+str(thelist))
	for item in thelist:
		print_d("[DEBUG] [FindElement] String is "+string+", item is "+item)
		if string == item: 
			return True
			break
	return False
def shrinkURL(url):
	tinyurl_api = "http://tinyurl.com/api-create.php?url="
	# Check for name links included in the url (like #here)...
	split_url = url.split('#')
	base_url = split_url[0]
	quoted_url = urllib.quote_plus(base_url)
	
	COUNTED_TFAILS = 0
	
	try:
		tinyurl_conn = urllib2.urlopen(tinyurl_api + quoted_url)
		tinyurl_out = tinyurl_conn.read()
		tinyurl_conn.close()
		COUNTED_TFAILS = 0
		TINYURL_FAILED = 0
	except urllib2.HTTPError, e:
		print_d("[TinyURLCreate] Cannot retrieve URL: HTTP Error Code "+str(e.code))
		COUNTED_TFAILS = COUNTED_TFAILS + 1
		TINYURL_FAILED = 1
	except urllib2.URLError, e:
		print_d("[TinyURLCreate] Cannot retrieve URL: " + str(e.reason[1]))
		COUNTED_TFAILS = COUNTED_TFAILS + 1
		TINYURL_FAILED = 1
	
	if TINYURL_FAILED == 1:
		if COUNTED_TFAILS == 5:
			print_d("[TinyURLCreate] TinyURL is down, posting message...")
			logToFile("[TinyURLCreate] TinyURL is down... (retried 5 times and failed)")
			for chan in IN_CHANS:
				if (not(findelement(chan, SILENTCHANS))):
					s.sendall("PRIVMSG "+chan+" :\x034TinyURL is down at the moment, so some links may not be shortened.\x03\r\n")
		if COUNTED_TFAILS >= 5:
			print_d("[TinyURLCreate] TinyURL is down, returning 1...")
			return 1
		print_d("[TinyURLCreate] Retrying URL creation...")
		retry = shrinkURL(url)
		return retry
	if len(split_url) > 1:
		final_url = tinyurl_out + "#" + split_url[1]
	else:
		final_url = tinyurl_out
	return final_url

def unescape(text):
	def fixup(m):
		text = m.group(0)
		if text[:2] == "&#":
			# character reference
			try:
				if text[:3] == "&#x":
					return unichr(int(text[3:-1], 16))
				else:
					return unichr(int(text[2:-1]))
			except ValueError:
				pass
		else:
			# named entity
			try:
				text = unichr(htmlentitydefs.name2codepoint[text[1:-1]])
			except KeyError:
				pass
		return text # leave as is
	return re.sub("&#?\w+;", fixup, text)
def truncate_me(content, length=30, suffix='...'):
	if len(content) <= length:
		return content
	else:
		return ' '.join(content[:length+1].split(' ')[0:-1]) + suffix
def removeBadWords(thestr):
	for badword in BADWORDS:
		newstr = thestr.replace(badword, '[explicit]')
		thestr = newstr
	return thestr

def CleanString(InputString):
	from string import ascii_letters, digits
	return "".join([ch for ch in InputString if ch in (ascii_letters + digits)])

def getTraceBack():
	et, ev, tb = sys.exc_info()
	while tb :
		co = tb.tb_frame.f_code
		filename = "Filename: " + str(co.co_filename)
		line_no =  "Error line #: " + str(traceback.tb_lineno(tb)) 
		tb = tb.tb_next
	return [filename, line_no, et, ev]

def crashFail(err):
	the_err = getTraceBack()
	fn = the_err[0]
	linen = the_err[1]
	et = the_err[2]
	ev = the_err[3]
	print_i("[CrashHandler] ERROR: Python crashed with: "+str(err)+" on line "+str(linen))
	print_i("[CrashHandler] Error type: "+str(et))
	print_i("[CrashHandler] Detailed error: "+str(ev))
	print_i("[CrashHandler] Traceback:")
	
	logToFile("[CrashHandler] ERROR: Python crashed with: "+str(err)+" on line "+str(linen))
	logToFile("[CrashHandler] Error type: "+str(et))
	logToFile("[CrashHandler] Detailed error: "+str(ev))
	logToFile("[CrashHandler] Traceback:")
	
	#traceback.print_exc(file=sys.stdout)
	exception_split = str(traceback.format_exc()).split("\n")
	for line in exception_split:
		print_i("[CrashHandler] "+line)
		logToFile("[CrashHandler] "+line)
	for chan in IN_CHANS: 
		if findelement(chan, NODIECHANS):
			print_d("Not showing message to "+chan+" due to settings...")
		else:
			if (not(findelement(chan, SILENTCHANS))):
				s.sendall("PRIVMSG "+chan+" :\x034I died - hopefully "+OWNER+" sees the error and fixes it. X_X\x03\r\n")
	if SEND_ERROR_TO_OWNER == 1:
		s.sendall("PRIVMSG "+OWNER+" :\x034I died - hopefully "+OWNER+" sees the error and fixes it. X_X\x03\r\n")
		s.sendall("PRIVMSG "+OWNER+" :\x034ERROR: Python crashed with: "+str(err)+" on line "+str(linen)+"\x03\r\n")
		s.sendall("PRIVMSG "+OWNER+" :\x034Error type: "+str(et)+"\x03\r\n")
def minorCrashFail(err):
	the_err = getTraceBack()
	fn = the_err[0]
	linen = the_err[1]
	et = the_err[2]
	ev = the_err[3]
	print_i("[CrashHandler] ERROR: Python crashed with: "+str(err)+" on line "+str(linen))
	print_i("[CrashHandler] Error type: "+str(et))
	print_i("[CrashHandler] Detailed error: "+str(ev))
	print_i("[CrashHandler] Traceback:")
	
	logToFile("[CrashHandler] ERROR: Python crashed with: "+str(err)+" on line "+str(linen))
	logToFile("[CrashHandler] Error type: "+str(et))
	logToFile("[CrashHandler] Detailed error: "+str(ev))
	logToFile("[CrashHandler] Traceback:")
	#traceback.print_exc(file=sys.stdout)
	exception_split = str(traceback.format_exc()).split("\n")
	for line in exception_split:
		print_i("[CrashHandler] "+line)
		logToFile("[CrashHandler] "+line)
def failExitBot():
	s.sendall("Junk stuff to get bot to exit\r\n")
	s.close()
	exit(1)

def logToFile(log):
	if LOG_TO_FILE == 1:
		try:
			logfh = open(LOGFILE, "a")
			curdt = datetime.datetime.now().strftime("[AtomBot | %m/%d/%Y %I:%M:%S %p]") 
			logfh.write(str(curdt)+" "+log+"\n")
			logfh.close()
		except Exception, err:
			if LOG_FAILED != 1:
				print_e("[Logger] ==========================================================")
				print_e("[Logger] ERROR: Failed to log to file! Make sure that the file is")
				print_e("[Logger] accessible, and that you have the proper permissions to ")
				print_e("[Logger] write to the file (or in the directory).")
				print_e("[Logger] ==========================================================")
				LOG_FAILED = 1
def checkLogFilePerm():
	if LOG_TO_FILE == 1:
		try:
			logfh = open(LOGFILE, "a")
			logfh.close()
		except Exception, err:
			print_e("[Logger] ==========================================================")
			print_e("[Logger] ERROR: The bot has detected that there is no way to write")
			print_e("[Logger] to the log file, since permissions for the file are")
			print_e("[Logger] limited. Make the log file writable, and then try again.")
			print_e("[Logger] Alternatively, you may disable the logging feature by")
			print_e("[Logger] setting LOG_TO_FILE to 0 (inside the script, not")
			print_e("[Logger] environmental variable).")
			print_e("[Logger] ==========================================================")
			exit(1)
def startLog():
	if LOG_TO_FILE == 1:
		startdt = datetime.datetime.now().strftime("%m/%d/%Y at %I:%M:%S %p") 
		logToFile("=====================================================================")
		logToFile("Log start: "+startdt)
		logToFile("=====================================================================")
def joinChannel(chan):
	global s, IN_CHANS
	if(not(findelement(chan, IN_CHANS))):
		s.sendall("JOIN %s \r\n" % chan)
		IN_CHANS.append(chan)
def leaveChannel(chan):
	global s, IN_CHANS
	if(findelement(chan, IN_CHANS)):
		s.sendall("PART %s \r\n" % chan)
		IN_CHANS.remove(chan)

class RestartThread ( threading.Thread ):
	def __init__ ( self, channel, details ):
		self.stopnow = 0
		threading.Thread.__init__(self)
	def stopThread(self):
		print_r("[RestartThread] Got signal to exit.")
		self.stopnow = 1
	def checkExit(self):
		if self.stopnow == 1:
			print_r("Adios from RestartThread thread!")
			exit()
	def run (self):
		print_i("[RestartThread] Waiting for restart...")
		time.sleep(5)
		print_i("[RestartThread] Launching bot...")
		subprocess.Popen([sys.executable, sys.argv[0]])
		print_i("[RestartThread] Launched bot, closing thread...")
		exit()

def parsemsg(msg): 
	global DISABLE_RAW_COMMAND
	print_r("[ParseMsg] Parsing message...")
	# IPv6 breaks some things
	# :alb|ZNC!albert@2607:fcd0:100:c21:216:3cff:fead:91a PRIVMSG #nspire-lua :%lua2tns
	#complete=msg[1:].split(':',1) #Parse the message into useful data 
	#info=complete[0].split(' ') 
	#msgpart=complete[1] 
	#sender=info[0].split('!') 
	
	# USEFUL VARIABLES: info, msgpart, and sender
	info = msg[1:].split(" ")[:-1]
	msgpart = msg[1:].split(" ")[-1][1:]
	sender = msg[1:].split(" ")[0].split("!")
	
	if len(msgpart) != 0:
		print_d("[DEBUG] msgpart[0] is "+msgpart[0])
	else:
		return 1
	print_d("[DEBUG] sender[0] is "+sender[0].strip(' '))
	print_d("[DEBUG] info[2] is "+info[2])
	print_d("[DEBUG] OWNER is "+OWNER)
	if msgpart[0]==CALLCHAR:
		print_d("[DEBUG] msgpart is verified!")
	if sender[0].strip(' ')==OWNER:
		print_d("[DEBUG] sender/OWNER is verified!")
	if msgpart[0]==CALLCHAR and (sender[0].strip(' ')==OWNER or (OPS_CAN_CONTROL_BOT == 1 and findelement(sender[0].strip(' '), OPS))):
		print_r("[ParseMsg] Looking for commands...")
		
		print_d("[ParseMsg] [DEBUG] Spliting command...")
		
		print_d("[DEBUG] msgpart[1:] is "+str(msgpart[1:]))
		cmd=msgpart[1:].split(' ') 
		
		if len(cmd) == 0:
			return 1
		
		if len(cmd) > 1:
			print_d("[DEBUG] cmd[1] is "+str(cmd[1]))
		
		if cmd[0]=='op': 
			if len(cmd) < 2:
				s.sendall('MODE '+info[2]+' +o '+sender[0]+'\n') 
				print_r("[ParseMsg] Op-ed "+sender[0]+" in "+info[2]+"...")
			else:
				s.sendall('MODE '+info[2]+' +o '+cmd[1]+'\n') 
				print_r("[ParseMsg] Op-ed "+cmd[1]+" in "+info[2]+"...")
		if cmd[0]=='deop': 
			if len(cmd) < 2:
				s.sendall('MODE '+info[2]+' -o '+sender[0]+'\n') 
				print_r("[ParseMsg] Deop-ed "+sender[0]+" in "+info[2]+"...")
			else:
				s.sendall('MODE '+info[2]+' -o '+cmd[1]+'\n') 
				print_r("[ParseMsg] Deop-ed "+cmd[1]+" in "+info[2]+"...")
		if cmd[0]=='sys': 
			if RUN_SYS_COMMANDS == 1:
				syscmd(msgpart[1:],info[2]) 
				print_r("[ParseMsg] Running "+msgpart[1]+"...")
			else:
				s.sendall("PRIVMSG "+info[2]+" :System commands are not allowed to be ran. To allow them,\r\n")
				s.sendall("PRIVMSG "+info[2]+" :set RUN_SYS_COMMANDS to 1.\r\n")
		if cmd[0]=='leave':
			if len(cmd) < 2:
				leaveChannel(info[2])
				print_r("[ParseMsg] Leaving channel "+info[2]+"...")
			else:
				leaveChannel(cmd[1])
				print_r("[ParseMsg] Leaving channel "+cmd[1]+"...")
		if cmd[0]=='join':
			if len(cmd) < 2:
				joinChannel(info[2])
				print_r("[ParseMsg] Joining channel "+info[2]+"...")
			else:
				joinChannel(cmd[1])
				print_r("[ParseMsg] Joining channel "+cmd[1]+"...")
		if cmd[0]=='silence':
			if len(cmd) < 2:
				SILENTCHANS.append(info[2])
				print_r("[ParseMsg] Silencing bot in channel "+info[2]+"...")
			else:
				SILENTCHANS.append(cmd[1])
				print_r("[ParseMsg] Silencing bot in channel "+cmd[1]+"...")
		if cmd[0]=='enable':
			if len(cmd) < 2:
				SILENTCHANS.remove(info[2])
				print_r("[ParseMsg] Enabling bot in channel "+info[2]+"...")
			else:
				SILENTCHANS.remove(cmd[1])
				print_r("[ParseMsg] Enabling bot in channel "+cmd[1]+"...")
		if cmd[0]=='about':
			if (findelement(info[2], COLORFULCHANS)):
				s.sendall("PRIVMSG "+info[2]+" :\x034AtomBot Lua2TNS v"+str(VERSION)+" by Albert H (alberthro) | Lua2TNS core by JayTe |  Python version:\x0310 "+str(sys.version).replace(' \n', ', compiled with ')+"\x034 | XML Core:\x0310 xml.dom.minidom\x034 | Bot owner:\x033 "+OWNER+" \x034| Licensed under GPL v3 | Thanks to Levak, Adriweb, and apcalc for the inspiration, and everybody at \x0302#cemetech \x0304and \x0302#omnimaga \x0304who helped me develop and test this! :D | Website: \x032http://code.google.com/p/atombot/\x0F\r\n")
			else:
				s.sendall("PRIVMSG "+info[2]+" :AtomBot Lua2TNS v"+str(VERSION)+" by Albert H (alberthro) | Lua2TNS core by JayTe | Python version: "+str(sys.version).replace(' \n', ', compiled with ')+" | XML Core: xml.dom.minidom | Bot owner: "+OWNER+" | Licensed under GPL v3 | Thanks to Levak, Adriweb, and apcalc for the inspiration, and everybody at #cemetech and #omnimaga who helped me develop and test this! :D | Website: http://code.google.com/p/atombot/\r\n")
		if cmd[0]=='restart':
			print_r("[ParseMsg] Restarting bot...")
			if (findelement(info[2], COLORFULCHANS)):
				s.sendall("PRIVMSG "+info[2]+" :\x034Restarting AtomBot...\x0F\r\n")
			else:
				s.sendall("PRIVMSG "+info[2]+" :Restarting AtomBot...\r\n")
			s.sendall("Junk stuff to get bot to exit\r\n")
			s.close()
			RestartThreadHandler = RestartThread(None, "")
			RestartThreadHandler.start()
			exit()
		if cmd[0]=='quit': 
			print_r("[ParseMsg] Exiting bot and closing socket...")
			s.close()
			exit()
		if cmd[0]=='say':
			if len(cmd) < 2:
				print_r("[ParseMsg] User wanted to make the bot say something, but didn't specify what to say...")
				s.sendall("PRIVMSG "+info[2]+" :What to say?\r\n")
			else:
				print_r("[ParseMsg] Saying words... (Word is "+str(" ".join(cmd[1:]))+")")
				s.sendall("PRIVMSG "+info[2]+" :"+str(" ".join(cmd[1:]))+"\r\n")
		if cmd[0]=='raw':
			if len(cmd) < 2:
				print_r("[ParseMsg] User wanted to make the bot execute a raw command in IRC, but didn't specify what to execute...")
				s.sendall("PRIVMSG "+info[2]+" :What to execute?\r\n")
			else:
				if DISABLE_RAW_COMMAND == 1:
					print_r("[ParseMsg] Raw command is disabled, so not doing anything.")
				else:
					print_r("[ParseMsg] Executing command... (Command is "+str(" ".join(cmd[1:]))+")")
					s.sendall(str(" ".join(cmd[1:]))+"\r\n")
		if cmd[0]=='nick':
			if len(cmd) < 2:
				print_r("[ParseMsg] Changing nick to "+info[2]+"...")
				NICK = info[2]
				s.sendall("NICK %s\r\n" % info[2])
			else:
				print_r("[ParseMsg] Changing nick to "+cmd[1]+"...")
				NICK = cmd[1]
				s.sendall("NICK %s\r\n" % cmd[1])
	cmd=msgpart[1:].split(' ') 
	print_r("[ParseMsg] Found command "+str(cmd[0])+" (non-admin)...")
	print_r("[ParseMsg] Looking for commands (non-admin)...")
	
	print_d("[ParseMsg] [DEBUG] Spliting command (non-admin)...")
	
	print_d("[DEBUG] msgpart[1:] is "+str(msgpart[1:]) + " (non-admin)...")
	
	if len(cmd) == 0:
		return 1
	
	if len(cmd) > 1:
		print_d("[DEBUG] cmd[1] is "+str(cmd[1])+ " (non-admin)...")
	if cmd[0]=='lua2tns':
		if len(cmd) < 2:
			# Show the help.
			s.sendall('PRIVMSG '+info[2]+" :Lua2TNS Help | :lua2tns [Pastebin Source URL] [Output file name (like helloworld.tns, etc.)]\r\n")
		else:
			if len(cmd) == 3:
				ConvertItHandler = ConvertIt(s, info[2], sender[0], cmd[1], cmd[2])
				ConvertItHandler.start()
			else:
				s.sendall('PRIVMSG '+info[2]+" :"+sender[0]+": Invalid number of arguments! Usage: | :lua2tns [Pastebin Source URL] [Output file name (like helloworld.tns, etc.)]\r\n")

def syscmd(commandline,channel): 
	cmd=commandline.replace('sys ','') 
	cmd=cmd.rstrip() 
	os.system(cmd+' >temp.txt') 
	a=open('temp.txt') 
	ot=a.read() 
	ot.replace('n','|') 
	a.close() 
	s.sendall('PRIVMSG '+channel+' :'+ot+'n') 
	return 0 

print_i("AtomBot Lua2TNS v"+str(VERSION)+" by Albert H")
print_i("========================================")
print_i("Starting IRC bot...")
print_i("")

checkLogFilePerm()
startLog()

s=socket.socket( )
s.connect((HOST, PORT))
if PASS != '':
	s.sendall("PASS %s\r\n" % PASS)
s.sendall("NICK %s\r\n" % NICK)
s.sendall("USER %s %s bla :%s\r\n" % (IDENT, HOST, REALNAME))

print_d("BOT: Entering main loop")
while 1:
	try:
		readbuffer=readbuffer+s.recv(1024)
	except:
		print_i("Connection closed, exiting.")
		break
	temp=string.split(readbuffer, "\n")
	readbuffer=temp.pop()
	
	for line in temp:
		print_r("[IRC] "+line)
		line=string.rstrip(line)
		line=string.split(line)
		
		print_d("[DEBUG] line is "+str(line))
		print_d("[DEBUG] Elements in line:"+str(len(line)))
		print_d("[DEBUG] line[1] is "+line[1])
		print_d("[DEBUG] line[0].split('!')[0][1:] is "+line[0].split('!')[0][1:])
	
		try:
			print_d("[DEBUG] Checking for PING...")
			if(line[0]=="PING"):
				s.sendall("PONG %s\r\n" % line[1])
			
			#print_d("[DEBUG] Checking for :hi...")
			#if(len(line)>= 4 and line[3]==":hi"):
			#	s.sendall("JOIN %s \r\n" % CHANNELINIT)
			
			print_d("[DEBUG] Checking for 'End of /MOTD command'...")
			if(str(" ".join(line)).find('End of /MOTD command.') != -1):
				for chan in CHANNELINIT:
					print_r("[IRC] [Autojoin] Joining IRC channel: "+chan)
					joinChannel(chan)
					if (findelement(chan, ANNOUNCECHANS)):
						if (not(findelement(chan, SILENTCHANS))):
							s.sendall("PRIVMSG "+chan+" :"+ANNOUNCEMSG+"\r\n")
				IRC_CONNECTED=1
			
			print_d("[DEBUG] Checking for PRIVMSG...")
			if(CleanString(str(" ".join(line))).find('PRIVMSG') != -1): #Call a parsing function 
				print_r("[IRC] [PRIVMSG] Recieved private message, looking at it.")
				parsemsg(str(" ".join(line)))
#				[IRC] :AaronBot!arthur@pool-71-248-45-89.bltmmd.east.verizon.net JOIN :#thebot
			
			print_d("[DEBUG] Checking for user joining...")
			if(len(line)>=2 and line[1] == 'JOIN' and findelement(line[0].split('!')[0][1:], OPS)):
				print_r("[IRC] [AUTO OP] User "+line[0].split('!')[0][1:]+" has logged in and is in the op database,")
				print_r("[IRC] [AUTO OP] so automatically oping the user.")
				s.sendall('MODE '+line[2][1:]+' +o '+line[0].split('!')[0][1:]+'\n') 
			
			print_d("[DEBUG] Checking for KICK...")
			if(len(line)>=4 and line[1] == 'KICK' and findelement(line[2], IN_CHANS) and line[3] == NICK and line[4] == ':'+NICK):
				print_r("[IRC] [Autorejoin] Checking if channel is in autoconnect list...")
				if findelement(line[2], AUTOREJOIN_CHANS):
					print_r("[IRC] [Autorejoin] Rejoining "+NICK+"...")
					s.sendall("JOIN %s \r\n" % chan)
#				[IRC] :alberthro!arthur@pool-108-12-167-63.bltmmd.east.verizon.net KICK #thebot Omnom :Omnom
		except Exception, err:
			minorCrashFail(err)
